package com.eastfair.home.service.impl;

import cn.hutool.core.bean.BeanUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.eastfair.annotation.annotation.cache.Cache;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.home.dao.ReportServiceAuditMapper;
import com.eastfair.home.dto.ReportServiceAuditDTO;
import com.eastfair.home.dto.ReportSpaceAuditDTO;
import com.eastfair.home.entity.ReportEarnestMoneyAudit;
import com.eastfair.home.entity.ReportServiceAudit;
import com.eastfair.home.entity.ReportServiceAuditHistory;
import com.eastfair.home.entity.ReportSpaceAudit;
import com.eastfair.home.exceptioncode.HomeExceptionCode;
import com.eastfair.home.service.ReportEarnestMoneyAuditService;
import com.eastfair.home.service.ReportServiceAuditHistoryService;
import com.eastfair.home.service.ReportServiceAuditService;
import com.eastfair.home.vo.ReportEarnestMoneyAuditVO;
import com.eastfair.home.vo.ReportServiceAuditVO;
import com.eastfair.venuebooking.api.ServiceBookingFeign;
import com.eastfair.venuebooking.api.ServiceCategoryFeign;
import com.eastfair.venuebooking.api.ServiceSpecsFeign;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dto.ServiceBookingDTO;
import com.eastfair.venueservice.vo.ServiceCategoryVO;
import com.eastfair.venueservice.vo.ServiceSpecsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 报馆服务审核记录
 * </p>
 *
 * @author linan
 * @date 2022-08-08
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ReportServiceAuditServiceImpl extends SuperServiceImpl<ReportServiceAuditMapper, ReportServiceAudit> implements ReportServiceAuditService {


    @Resource
    private ReportServiceAuditHistoryService reportServiceAuditHistoryService;
    @Resource
    private ServiceCategoryFeign serviceCategoryFeign;
    @Resource
    private ServiceSpecsFeign serviceSpecsFeign;
    @Resource
    private ServiceBookingFeign serviceBookingFeign;
    @Resource
    private ReportEarnestMoneyAuditService reportEarnestMoneyAuditService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ReportServiceAudit> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ReportServiceAudit model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setTenantId(ContextUtil.getTenantId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public Boolean saveReportServiceAudit(List<ReportServiceAuditDTO> reportServiceAuditList) {
        if (CollectionUtils.isEmpty(reportServiceAuditList)) {
            throw BizException.wrap(HomeExceptionCode.SERVICE_CANT_EMPTY);
        }
        // 先删除之前的审核数据
        ReportServiceAuditDTO reportServiceAuditDTO = reportServiceAuditList.get(0);
        Long reportSpaceId = reportServiceAuditDTO.getReportSpaceId();
        baseMapper.delete(new QueryWrapper<ReportServiceAudit>().lambda()
                .eq(ReportServiceAudit::getIsDeleted,BusinessConstant.NO)
                .eq(ReportServiceAudit::getReportSpaceId,reportSpaceId));
        ArrayList<ReportServiceAudit> reportServiceAudits = new ArrayList<>();
        for (ReportServiceAuditDTO serviceAuditDTO : reportServiceAuditList) {
            ReportServiceAudit reportServiceAudit = BeanUtil.copyProperties(serviceAuditDTO, ReportServiceAudit.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
            handlerSave(reportServiceAudit);
            reportServiceAudits.add(reportServiceAudit);
        }
        return saveBatch(reportServiceAudits);
    }

    @Override
    public boolean saveReportServiceAudit(ReportSpaceAuditDTO reportSpaceAuditDTO, ReportSpaceAudit reportSpaceAudit) {
        // 提交管理费服务
        R<List<ReportServiceAuditDTO>> serviceBookResult = serviceBookingFeign.submitServiceBookingWhenReport(reportSpaceAuditDTO.getReportSpaceId(), reportSpaceAudit.getId());
        if (!serviceBookResult.getIsSuccess()) {
            throw new BizException(serviceBookResult.getCode(), serviceBookResult.getMsg());
        }
        List<ReportServiceAuditDTO> reportServiceAuditList = serviceBookResult.getData();
        if (CollectionUtils.isEmpty(reportServiceAuditList)) {
            throw BizException.wrap(HomeExceptionCode.SERVICE_CANT_EMPTY);
        }
        // 保存服务审核记录
        saveReportServiceAudit(reportServiceAuditList);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitServiceAudit(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        // 要提交的服务
        List<ReportServiceAuditDTO> reportServiceAuditList = reportSpaceAuditDTO.getReportServiceAuditList();
        Map<Long, ReportServiceAuditDTO> submitList = reportServiceAuditList.stream().collect(Collectors.toMap(ReportServiceAuditDTO::getId, Function.identity()));
        // 查询提交的审核记录
        List<Long> ids = new ArrayList<>(submitList.keySet());
        // 更新审核状态，并插入历史记录
        List<ReportServiceAudit> reportServiceAudits = listByIds(ids);
        LocalDateTime now = LocalDateTime.now();
        // 回填服务预订的状态
        List<ServiceBookingDTO> serviceBookings = new ArrayList<>();
        for (ReportServiceAudit reportServiceAudit : reportServiceAudits) {
            Long id = reportServiceAudit.getId();
            ReportServiceAuditDTO reportServiceAuditDTO = submitList.get(id);
            reportServiceAudit.setAuditState(reportServiceAuditDTO.getAuditState());
            reportServiceAudit.setAuditOpinion(reportServiceAuditDTO.getAuditOpinion());
            reportServiceAudit.setAuditUserId(reportServiceAuditDTO.getAuditUserId());
            reportServiceAudit.setAuditUserName(reportServiceAuditDTO.getAuditUserName());
            reportServiceAudit.setDiscount(reportServiceAuditDTO.getDiscount());
            reportServiceAudit.setAuditTime(now);
            updateById(reportServiceAudit);
            ReportServiceAuditHistory reportServiceAuditHistory= BeanUtil.copyProperties(reportServiceAudit, ReportServiceAuditHistory.class,CommonConstants.COMMON_IGNORE_PROPERTIES);
            reportServiceAuditHistoryService.save(reportServiceAuditHistory);
            ServiceBookingDTO serviceBooking = BeanUtil.copyProperties(reportServiceAudit, ServiceBookingDTO.class);
            serviceBooking.setDiscount(reportServiceAuditDTO.getDiscount());
            serviceBooking.setUnitPriceAfterDiscount(reportServiceAuditDTO.getUnitPriceAfterDiscount());
            serviceBooking.setSubtotalServicePrice(reportServiceAuditDTO.getSubtotalServicePrice());
            serviceBooking.setSubtotalPrice(reportServiceAuditDTO.getSubtotalPrice());
            serviceBookings.add(serviceBooking);
        }
        serviceBookingFeign.updateServiceBookingAuditResult(serviceBookings);
        return true;
    }


    @Override
    public Boolean saveServiceAudit(List<ReportServiceAuditDTO> reportServiceAudits) {
        List<ReportServiceAudit> serviceAuditList = reportServiceAudits.stream().map(e -> {
            ReportServiceAudit reportServiceAudit = new ReportServiceAudit();
            reportServiceAudit.setId(e.getId());
            reportServiceAudit.setAuditState(e.getAuditState());
            reportServiceAudit.setAuditOpinion(e.getAuditOpinion());
            return reportServiceAudit;
        }).collect(Collectors.toList());
        return updateBatchById(serviceAuditList);
    }

    @Override
    public Boolean delServiceAuditByReportSpaceId(Long reportSpaceId) {
        return update(new UpdateWrapper<ReportServiceAudit>().lambda()
                .eq(ReportServiceAudit::getIsDeleted,BusinessConstant.NO)
                .eq(ReportServiceAudit::getReportSpaceId,reportSpaceId).set(ReportServiceAudit::getIsDeleted,BusinessConstant.YES));
    }

    @Override
    public ReportEarnestMoneyAuditVO queryReportEarnestMoneyAudit(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        ReportEarnestMoneyAudit reportEarnestMoneyAudit = reportEarnestMoneyAuditService.getOne(new QueryWrapper<ReportEarnestMoneyAudit>().lambda()
                .eq(ReportEarnestMoneyAudit::getIsDeleted, BusinessConstant.NO)
                .eq(ReportEarnestMoneyAudit::getReportSpaceId, reportSpaceAuditDTO.getReportSpaceId()));
        if (Objects.nonNull(reportEarnestMoneyAudit)) {
            return BeanUtil.copyProperties(reportEarnestMoneyAudit, ReportEarnestMoneyAuditVO.class);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByItem(List<ReportServiceAuditDTO> reportServiceAuditDTOS) {
        for (ReportServiceAuditDTO reportServiceAuditDTO : reportServiceAuditDTOS) {
            update(new UpdateWrapper<ReportServiceAudit>().lambda()
                    .eq(ReportServiceAudit::getServiceItemId, reportServiceAuditDTO.getServiceItemId())
                    .eq(ReportServiceAudit::getServiceCategoryId, reportServiceAuditDTO.getServiceCategoryId())
                    .eq(ReportServiceAudit::getServiceSpecsId, reportServiceAuditDTO.getServiceSpecsId())
                    // 只修改未生成订单的
                    .ne(ReportServiceAudit::getGenerateOrder, BusinessConstant.NO)
                    .eq(ReportServiceAudit::getIsDeleted, BusinessConstant.NO)
                    // 服务名称
                    .set(ReportServiceAudit::getServiceName, reportServiceAuditDTO.getServiceName())
                    // 服务图片
                    .set(ReportServiceAudit::getPicUrl, reportServiceAuditDTO.getPicUrl())
                    // 计量单位
                    .set(ReportServiceAudit::getCalUnit, reportServiceAuditDTO.getCalUnit())
                    // 服务单价
                    .set(ReportServiceAudit::getUnitPrice, reportServiceAuditDTO.getUnitPrice())
                    // 附加费
                    .set(ReportServiceAudit::getSurcharge, reportServiceAuditDTO.getSurcharge()));
        }
        return true;
    }

    @Override
    public List<ReportServiceAuditVO> queryReportServiceAuditList(ReportSpaceAuditDTO reportSpaceAuditDTO) {
        // 查询列表
        List<ReportServiceAudit> list = list(new QueryWrapper<ReportServiceAudit>().lambda()
                .eq(ReportServiceAudit::getReportSpaceId, reportSpaceAuditDTO.getReportSpaceId())
                .eq(ReportServiceAudit::getIsDeleted, BusinessConstant.NO)
                .orderByAsc(ReportServiceAudit::getServiceName));
        // 查询服务类别和规格
        List<Long> categoryIds = list.stream().map(ReportServiceAudit::getServiceCategoryId).collect(Collectors.toList());
        List<Long> serviceSpecsIds = list.stream().map(ReportServiceAudit::getServiceSpecsId).collect(Collectors.toList());
        R<List<ServiceCategoryVO>> categoryListByIds = serviceCategoryFeign.getCategoryListByIds(categoryIds);
        R<List<ServiceSpecsVO>> serviceSpecsByIds = serviceSpecsFeign.getServiceSpecsByIds(serviceSpecsIds);
        Map<Long, ServiceCategoryVO> serviceCategoryVOMap = categoryListByIds.getData().stream().collect(Collectors.toMap(ServiceCategoryVO::getId, Function.identity()));
        Map<Long, ServiceSpecsVO> serviceSpecsVOMap = serviceSpecsByIds.getData().stream().collect(Collectors.toMap(ServiceSpecsVO::getId, Function.identity()));
        List<ReportServiceAuditVO> reportServiceAuditVOS = new ArrayList<>();
        // 遍历
        for (ReportServiceAudit reportServiceAudit : list) {
            ReportServiceAuditVO reportServiceAuditVO = BeanUtil.copyProperties(reportServiceAudit, ReportServiceAuditVO.class);
            ServiceCategoryVO serviceCategoryVO = serviceCategoryVOMap.get(reportServiceAudit.getServiceCategoryId());
            ServiceSpecsVO serviceSpecsVO = serviceSpecsVOMap.get(reportServiceAudit.getServiceSpecsId());
            if(Objects.nonNull(serviceCategoryVO)){
                reportServiceAuditVO.setServiceCategoryName(serviceCategoryVO.getServiceCategoryName());
            }
            if(Objects.nonNull(serviceSpecsVO)){
                reportServiceAuditVO.setServiceSpecsName(serviceSpecsVO.getServiceSpecsName());
            }
            reportServiceAuditVOS.add(reportServiceAuditVO);
        }
        return reportServiceAuditVOS;
    }

}
